#include "gtkliststore.h"
#include "gtkmain.h"
#include "gtkmenu.h"
+#include "gtktearoffmenuitem.h"
#include "gtktogglebutton.h"
#include "gtktreeselection.h"
#include "gtkvseparator.h"
guint popup_in_progress : 1;
guint destroying : 1;
+ guint add_tearoffs : 1;
};
/* While debugging this evil code, I have learned that
PROP_WRAP_WIDTH,
PROP_ROW_SPAN_COLUMN,
PROP_COLUMN_SPAN_COLUMN,
- PROP_ACTIVE
+ PROP_ACTIVE,
+ PROP_ADD_TEAROFFS
};
static GtkBinClass *parent_class = NULL;
0,
G_PARAM_READWRITE));
+ /**
+ * GtkComboBox:add-tearoffs:
+ *
+ * The "add-tearoffs" property controls whether generated menus
+ * have tearoff menu items.
+ *
+ * Note that this only affects menu style combo boxes.
+ *
+ * Since: 2.6
+ */
+ g_object_class_install_property (object_class,
+ PROP_ADD_TEAROFFS,
+ g_param_spec_boolean ("add-tearoffs",
+ P_("Add tearoffs to menus"),
+ P_("Whether combobox dropdowns should have a tearoff menu item"),
+ FALSE,
+ G_PARAM_READWRITE));
+
gtk_widget_class_install_style_property (widget_class,
g_param_spec_boolean ("appears-as-list",
P_("Appears as list"),
gtk_combo_box_set_active (combo_box, g_value_get_int (value));
break;
+ case PROP_ADD_TEAROFFS:
+ gtk_combo_box_set_add_tearoffs (combo_box, g_value_get_boolean (value));
+ break;
+
default:
break;
}
g_value_set_int (value, gtk_combo_box_get_active (combo_box));
break;
+ case PROP_ADD_TEAROFFS:
+ g_value_set_boolean (value, gtk_combo_box_get_add_tearoffs (combo_box));
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
{
GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
+ combo_box->priv->popup_in_progress = TRUE;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (combo_box->priv->button),
TRUE);
combo_box->priv->popup_in_progress = FALSE;
combo_box = GTK_COMBO_BOX (widget);
g_return_if_fail (combo_box->priv->popup_widget == (GtkWidget*) menu);
- g_signal_handlers_disconnect_by_func (menu,
+ g_signal_handlers_disconnect_by_func (menu->toplevel,
gtk_combo_box_menu_show,
combo_box);
- g_signal_handlers_disconnect_by_func (menu,
+ g_signal_handlers_disconnect_by_func (menu->toplevel,
gtk_combo_box_menu_hide,
combo_box);
combo_box->priv->popup_widget = popup;
- g_signal_connect (popup, "show",
+ /*
+ * Note that we connect to show/hide on the toplevel, not the
+ * menu itself, since the menu is not shown/hidden when it is
+ * popped up while torn-off.
+ */
+ g_signal_connect (GTK_MENU (popup)->toplevel, "show",
G_CALLBACK (gtk_combo_box_menu_show), combo_box);
- g_signal_connect (popup, "hide",
+ g_signal_connect (GTK_MENU (popup)->toplevel, "hide",
G_CALLBACK (gtk_combo_box_menu_hide), combo_box);
gtk_menu_attach_to_widget (GTK_MENU (popup),
items = gtk_tree_model_iter_n_children (combo_box->priv->model, NULL);
menu = combo_box->priv->popup_widget;
+ if (combo_box->priv->add_tearoffs)
+ {
+ GtkWidget *tearoff = gtk_tearoff_menu_item_new ();
+
+ gtk_widget_show (tearoff);
+
+ if (combo_box->priv->wrap_width)
+ gtk_menu_attach (GTK_MENU (menu), tearoff,
+ 0, combo_box->priv->wrap_width, 0, 1);
+ else
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), tearoff);
+ }
+
for (i = 0; i < items; i++)
{
GtkTreePath *path;
for (i = GTK_MENU_SHELL (menu)->children; i; i = i->next)
{
guint l, r, b, t;
- gboolean h_intersect = FALSE;
- gboolean v_intersect = FALSE;
gtk_container_child_get (GTK_CONTAINER (menu), i->data,
"left_attach", &l,
NULL);
/* look if this item intersects with the given coordinates */
- h_intersect = left_attach <= l && l <= right_attach;
- h_intersect &= left_attach <= r && r <= right_attach;
-
- v_intersect = top_attach <= t && t <= bottom_attach;
- v_intersect &= top_attach <= b && b <= bottom_attach;
-
- if (h_intersect && v_intersect)
- return TRUE;
+ if (right_attach > l && left_attach < r && bottom_attach > t && top_attach < b)
+ return TRUE;
}
return FALSE;
return;
list = gtk_container_get_children (GTK_CONTAINER (menu));
+ if (combo_box->priv->add_tearoffs)
+ list = list->next;
item = g_list_nth_data (list, index);
g_list_free (list);
{
gint index;
GtkWidget *menu;
+ GList *children;
GtkComboBox *combo_box = GTK_COMBO_BOX (user_data);
menu = combo_box->priv->popup_widget;
g_return_if_fail (GTK_IS_MENU (menu));
- index = g_list_index (GTK_MENU_SHELL (menu)->children, item);
+ children = GTK_MENU_SHELL (menu)->children;
+ if (combo_box->priv->add_tearoffs)
+ children = children->next;
+
+ index = g_list_index (children, item);
gtk_combo_box_set_active (combo_box, index);
}
gtk_tree_selection_set_mode (sel, GTK_SELECTION_SINGLE);
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (combo_box->priv->tree_view),
FALSE);
+ g_object_set (combo_box->priv->tree_view,
+ "hover_selection", TRUE,
+ NULL);
+
if (combo_box->priv->model)
gtk_tree_view_set_model (GTK_TREE_VIEW (combo_box->priv->tree_view),
combo_box->priv->model);
{
GtkCellView *view;
+ if (GTK_IS_TEAROFF_MENU_ITEM (i->data))
+ continue;
+
if (GTK_IS_CELL_VIEW_MENU_ITEM (i->data))
view = GTK_CELL_VIEW (GTK_BIN (i->data)->child);
else
{
GtkCellView *view;
+ if (GTK_IS_TEAROFF_MENU_ITEM (i->data))
+ continue;
+
if (GTK_IS_CELL_VIEW_MENU_ITEM (i->data))
view = GTK_CELL_VIEW (GTK_BIN (i->data)->child);
else
{
GtkCellView *view;
+ if (GTK_IS_TEAROFF_MENU_ITEM (i->data))
+ continue;
+
if (GTK_IS_CELL_VIEW_MENU_ITEM (i->data))
view = GTK_CELL_VIEW (GTK_BIN (i->data)->child);
else
{
GtkCellView *view;
+ if (GTK_IS_TEAROFF_MENU_ITEM (i->data))
+ continue;
+
if (GTK_IS_CELL_VIEW_MENU_ITEM (i->data))
view = GTK_CELL_VIEW (GTK_BIN (i->data)->child);
else
{
GtkCellView *view;
+ if (GTK_IS_TEAROFF_MENU_ITEM (i->data))
+ continue;
+
if (GTK_IS_CELL_VIEW_MENU_ITEM (i->data))
view = GTK_CELL_VIEW (GTK_BIN (i->data)->child);
else
{
GtkCellView *view;
+ if (GTK_IS_TEAROFF_MENU_ITEM (i->data))
+ continue;
+
if (GTK_IS_CELL_VIEW_MENU_ITEM (i->data))
view = GTK_CELL_VIEW (GTK_BIN (i->data)->child);
else
{
GtkCellView *view;
+ if (GTK_IS_TEAROFF_MENU_ITEM (i->data))
+ continue;
+
if (GTK_IS_CELL_VIEW_MENU_ITEM (i->data))
view = GTK_CELL_VIEW (GTK_BIN (i->data)->child);
else
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+
+
+gboolean
+gtk_combo_box_get_add_tearoffs (GtkComboBox *combo_box)
+{
+ g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), FALSE);
+
+ return combo_box->priv->add_tearoffs;
+}
+
+void
+gtk_combo_box_set_add_tearoffs (GtkComboBox *combo_box,
+ gboolean add_tearoffs)
+{
+ g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
+
+ add_tearoffs = add_tearoffs != FALSE;
+
+ if (combo_box->priv->add_tearoffs != add_tearoffs)
+ {
+ combo_box->priv->add_tearoffs = add_tearoffs;
+ gtk_combo_box_check_appearance (combo_box);
+ gtk_combo_box_relayout (combo_box);
+ g_object_notify (G_OBJECT (combo_box), "add_tearoffs");
+ }
+}